/**
 * Title：雷达手势识别装置-Arduino固件
 * Author：张浩
 * Data：2019年11月1日
 * Function：
 * 1、按键与LEDs驱动
 * 2、串口驱动数据包解析函数
 * 3、Radar IF信号ADC采样
 * From Air-CAS✈
 * Copyright © 2019 By HBB😀
 **/

/**
 * Include Files
 **/
#include <Arduino.h>
#include <MsTimer2.h>

/**
 * 接口宏定义
 * 对应V1.0 Board
 **/ 
#define Data_state_LED 5
#define Sys_Error_LED 4
#define KEY1_Pin 3
#define KEY2_Pin 2
#define Radar_Sig_Pin A0

/**
 * 全局变量
 * 
 **/ 
#define packageLen 50
int sampleFreq = 500;//Sample Rate = 500Hz
int sampleCycle = 2;//2ms

int pingData[packageLen] = {0};
int pongData[packageLen] = {0};

int pingReady = 0;
int pongReady = 0;
int pingpongFlag = 0;

int dataPointer = 0;

int state = 0;

/**
 * 启动采样并输出
 */
void startSample()
{
  //修改标志位
  state = 1;
  //将数据缓冲区清零
  int i = 0;
  for(i = 0; i < packageLen; i++)
  {
    pingData[i] = 0;
    pongData[i] = 0;
    }
   //数据指针指向ping缓冲区开头
   dataPointer = 0;
   //启动定时器采样
   MsTimer2::start();
   //修改指示灯状态
   digitalWrite(Data_state_LED,HIGH);
   digitalWrite(Sys_Error_LED,LOW);
  }

/**
 * IO端口初始化函数
 * 需要在SetUp函数中调用仅一次
 * input：void
 * output：void
 **/ 
void ioInit(){
  pinMode(Data_state_LED, OUTPUT);
  pinMode(Sys_Error_LED, OUTPUT);
  pinMode(KEY1_Pin, INPUT_PULLUP);
  pinMode(KEY2_Pin, INPUT_PULLUP);
}

/**
 * 按键检测函数
 * input：void
 * output：0-NULL 1-Key1_Pressed 2-Key2_pressed
 **/ 
int keyScan()
{
  if(digitalRead(KEY1_Pin) == LOW)
  {
    delay(10);
    if (digitalRead(KEY1_Pin) == LOW)
    {
      /* 确定按键按下  消除抖动 */
      while(!digitalRead(KEY1_Pin));
      return 1;
    }
  }
  if(digitalRead(KEY2_Pin) == LOW)
  {
    delay(10);
    if (digitalRead(KEY2_Pin) == LOW)
    {
      /* 确定按键按下  消除抖动 */
      while(!digitalRead(KEY2_Pin));
      return 2;
    }
  }
  return 0;
}

/**
 * 按键处理函数
 * input：keyValue
 * return：void
 **/ 
void keyProcess(int keyValue)
{
  switch (keyValue)
  {
  case 1:
    /* 启动采样并通过串口输出 */
    startSample();
    break;
  case 2:
    /* 暂停 */
    if(state)
    {
      state = 0;
      }
      else
      {
        state = 1;
        }
    break;

  default:
    return;
  }
}

/**
 * 系统错误
 */
void sysError()
{
  MsTimer2::stop();
  digitalWrite(Sys_Error_LED, HIGH);
  }


/**
 * ADC Samples
 * 
 **/ 
void adcSample()
{   
  if(state == 0)
  {
    return;
    }  
  //触发ADC采样
  if(pingpongFlag == 0)
  {
    digitalWrite(Data_state_LED,HIGH);
    //往pingData写数据
    if(pingReady == 0)
    {
      //如果pingData还没有满
      pingData[dataPointer] = analogRead(A0);
      //pingData[dataPointer] = 0x0102;
      dataPointer++;
      if(dataPointer == packageLen)
      {
        //如果写入这个ping缓冲区就满了
        //将pingReady信号置位，表示串口可以开始发送pingReady缓冲区的数据
        //检查pongReady信号是否是0，如果是0则开始将数据存入pong，否则报错亮灯
        pingReady = 1;
        //将dataPointer置为0
        dataPointer = 0;
        pingpongFlag = 1;
        if(pongReady != 0)
        {
          sysError();
          }
        }
        else
        {
          return;
          }
      }
      else
      {
        sysError();
        }
    }
    else
    {
      digitalWrite(Data_state_LED,LOW);
      //往pongData写数据
      if(pongReady == 0)
      {
        //如果pongData没满
        pongData[dataPointer] = analogRead(A0);
        dataPointer++;
        if(dataPointer == packageLen)
        {
          pongReady = 1;
          dataPointer = 0;
          pingpongFlag = 0;
          if(pingReady != 0)
          {
            sysError();
            }
          }
          else
          {
            return;
            }
        }
        else
        {
          sysError();
          }
      }
}


void setup() {
  ioInit();
  MsTimer2::set(sampleCycle, adcSample);
  MsTimer2::stop(); 
  Serial.begin(115200);
}

void loop() {
  int i = 0;
//Step1:检查串口启动命令
  if (Serial.available())
  {
    char cmd = Serial.read();
    if(cmd == '1')
    {
      startSample();
      } 
     else if(cmd == '0')
     {
      MsTimer2::stop();
      }
      else
      {
        sysError();
        }
  }
  if(pingReady == 1)
  {
    //如果pingData满了，将其发送出去
    i = 0;
    for(i = 0; i < packageLen; i++)
    {
      Serial.write(pingData[i]);
      pingData[i] = pingData[i]>>8;
      Serial.write(pingData[i]);
      pingData[i] = 0;
      }
    //标志位清零
    pingReady = 0;
    }
   if(pongReady == 1)
   {
    //如果pongData满了，将其发送出去
    i = 0;
    for(i = 0; i < packageLen; i++)
    {
      Serial.write(pongData[i]);
      pongData[i] = pongData[i]>>8;
      Serial.write(pongData[i]);
      pongData[i] = 0;
      }
    //标志位清零
    pongReady = 0;
    }
   keyProcess(keyScan());
}
